/*
 * The MIT License
 * Copyright (c) 2012 kc4.org
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */
package org.kc4.sso.auth.section;

import java.io.IOException;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * @author yoichi kikuchi
 *
 */
public abstract class ModelSection {

	private Logger logger = LoggerFactory.getLogger(this.getClass());

	private HttpServletRequest request;
	private HttpServletResponse response;

	/**
	 * リクエストに応対します。
	 *
	 * @throws InterruptedSectionException セクション内で処理が中断された場合。
	 */
	public abstract void execute() throws InterruptedSectionException;

	/**
	 * インスタンスを生成します。
	 *
	 * @param request リクエスト。
	 * @param response レスポンス。
	 */
	public ModelSection(HttpServletRequest request, HttpServletResponse response) {

		this.getLogger().debug("begin execution. " + this.getClass().getSimpleName());

		this.setRequest(request);
		this.setResponse(response);
	}

	/**
	 * リダイレクトします。
	 *
	 * @param url リダイレクト先の URL。
	 */
	protected void sendRedirect(String url) {

		this.sendRedirect(url, true);
	}

	/**
	 * リダイレクトします。
	 *
	 * @param url リダイレクト先の URL。
	 * @param requireEncodeRedirectURL URL をリダイレクトのためにエンコードするかどうかを設定します。
	 */
	protected void sendRedirect(String url, boolean requireEncodeRedirectURL) {

		try {

			String redirectUrl = requireEncodeRedirectURL ?
				this.getResponse().encodeRedirectURL(url) : url;

			this.getLogger().debug(String.format(
				"redirect to \"%s\"", redirectUrl));

			this.getResponse().sendRedirect(redirectUrl);
			return;
		}
		catch (IOException e) {

			throw new IllegalStateException(e);
		}
	}

	/**
	 * エラーコードを送信します。
	 *
	 * @param code エラーコード。
	 */
	protected void sendError(int code) {

		try {

			StackTraceElement[] el = Thread.currentThread().getStackTrace();

			for (StackTraceElement e : el) {

				System.out.println(e.getFileName() + " : " + e.getLineNumber());
				System.out.println("	" + e.getClassName() + " : " + e.getMethodName());
			}

			this.getLogger().debug(String.format("error to \"%s\"", code));
			this.getResponse().sendError(code);
			return;
		}
		catch (IOException e) {

			throw new IllegalStateException(e);
		}
	}

	/**
	 * request を取得します。
	 *
	 * @return request オブジェクト。
	 */
	protected HttpServletRequest getRequest() {
		return this.request;
	}

	/**
	 * request を設定します。
	 *
	 * @param request request オブジェクト。
	 */
	protected void setRequest(HttpServletRequest request) {
		this.request = request;
	}

	/**
	 * response を取得します。
	 *
	 * @return response オブジェクト。
	 */
	protected HttpServletResponse getResponse() {
		return this.response;
	}

	/**
	 * response を設定します。
	 *
	 * @param response response オブジェクト。
	 */
	protected void setResponse(HttpServletResponse response) {
		this.response = response;
	}

	/**
	 * logger を取得します。
	 *
	 * @return logger オブジェクト。
	 */
	protected Logger getLogger() {

		return this.logger;
	}
}
